package net.bingosoft.common.util; 

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import net.bingosoft.common.BeanHelper;

import org.dom4j.Document;
import org.dom4j.Element;

/**
 * 2007-5-15 下午12:36:55
 * Author:yangdongyu(yangdy@bingosoft.net)
 * ReadMe:树形控件生成帮助类
 * ChangeLog:
 */
public class Tree {
	/**
	 * 该树的父节点
	 */
	private Tree parent;
	/**
	 * 该树的子节点
	 */
	private Tree child;
	/**
	 * 该树的兄弟节点
	 */
	private Tree brother;
	/**
	 * 树上显示的标题
	 */
	private String label;
	/**
	 * 点击菜单时触发的js 脚本
	 */
	private String onClick="";
	/**
	 * 定义与该对象对应的js变量的标识组成部分之一
	 */
	private int variableId = count++;

	/**
	 * 变量计数器
	 */
	private static int count = 0;

	/**
	 * 树形节点js变量命名前缀
	 */
	public static String prefix = "node_";

	/**
	 * 是否该树只包含文件夹形式(whether this tree contains only folders)
	 */
	public static boolean ONLY_FOLDER = false;
	/**
	 * 是否该树显示input框
	 */
	private boolean showInput = false;
	/**
	 * input 框的类型,只能是radio或checkbox
	 */
	private String inputType;
	/**
	 * 带有选择框的树当点击选择框时触发的动作
	 */
	private String onCheck;
	/**
	 * 当前选择框是否选中,只对带有选择框的树有效
	 */
	private boolean isChecked = false;
	/**
	 * 当前树的值
	 */
	private String value="";
	/**
	 * 树的提示信息
	 */
	private String tip = "";
	/**
	 * 树的父节点信息
	 */
	private String parentNodeId; 
	/**
	 * 当前节点的Id
	 */
	private String nodeId;
	/**
	 * 树形节点默认显示的图标
	 */
	private String icon;
	/**
	 * 树形节点打开时显示的图标
	 */
	private String openIcon;


	private String imagePath;

	private boolean open;

	public boolean isOpen() {
		return open;
	}
	public void setOpen(boolean open) {
		this.open = open;
	}
	/**
	 * 构造一个树形控件并初始化上面显示的文字
	 *
	 * @param label 树形控件上显示的文字
	 */
	public Tree() {
		this.label = "emptyTree";
	}
	/**
	 * 构造一个树形控件并初始化上面显示的文字
	 *
	 * @param label 树形控件上显示的文字
	 */
	public Tree(String label) {
		this.label = label;
	}


	public boolean isLast(){
		return this.brother == null;
	}


	/**
	 * 构造一个树形控件并初始化上面显示的文字和点击时触发的动作
	 *
	 * @param label  树形控件上显示的文字
	 * @param script 点击树形控件时触发的动作
	 */
	public Tree(String label, String script) {
		this.label = label;
		if(script != null){
			this.onClick = script.startsWith("javascript:")? script : "javascript:" + script;
		}
	}


	public String getParentNodeId() {
		return parentNodeId;
	}

	public void setParentNodeId(String extInfo) {
		this.parentNodeId = extInfo;
	}

	public String getInputType() {
		return inputType;
	}

	public void setInputType(String inputType) {
		this.inputType = inputType;
	}

	public String getTip() {
		return tip;
	}
	public void setTip(String tip) {
		this.tip = tip;
	}
	/**
	 * 让当前树项前面显示一个checkbox
	 *
	 */
	public void showCheckbox(){
		this.showInput = true;
		this.inputType = "checkbox";
	}
	/**
	 * 让当前树项前面显示一个radio选择框
	 *
	 */
	public void showRadio(){
		this.showInput = true;
		this.inputType = "radio";
	}


	/**
	 * @param isChecked the isChecked to set
	 */
	public void setChecked(boolean isChecked) {
		if(showInput){
			this.isChecked = isChecked;	
		}
	}

	/**
	 * @param onCheck the onCheck to set
	 */
	public void setOnCheck(String onCheck) {
		this.onCheck = onCheck;
	}

	/**
	 * @param value the value to set
	 */
	public void setValue(String value) {
		this.value = value;
	}

	/**
	 * 判断当前节点是否是根节点
	 *
	 * @return boolean 如果是根节点,返回true
	 */
	public boolean isRoot() {
		return null == this.parent;
	}

	/**
	 * 获取树定义的变量名称
	 *
	 * @return 树定义的变量名称
	 */
	private String variable() {
		if (this.parent == null)
			return "root";
		//避免数字溢出
		if(count >= Integer.MAX_VALUE - 1000){
			count = 0;
		}
		return prefix + this.variableId;
	}

	/**
	 * 生成树形控件Tree 对应的javascript 代码
	 *
	 * @param tree 待生成js代码的树形控件对象
	 * @return js 返回生成 tree 代表的树形控件的js代码
	 */
	private static StringBuffer generateJS(Tree tree) {
		StringBuffer buffer = new StringBuffer();
		if (tree.isRoot()) {
			buffer.append(generateRoot(tree));
		} else {
			buffer.append(generateItem(tree));
		}
		if (tree.child != null) { // has child
			buffer.append(generateJS(tree.child));
		}
		if (tree.brother != null) { //has brother
			buffer.append(generateJS(tree.brother));
		}
		return buffer;
	}

	/**
	 * 获取生成该树形控件的js代码
	 *
	 * @return js 能生成该对象所代表的树形控件的js代码
	 */
	public String getTree() {
		return generateJS(this) + "\ndocument.write(root);";
	}


	public String getHTML(){
		return generateHTMLTree(this);
	}


	public int getChildrenCount(){
		int count = 0;
		Tree node = this;
		if(node.child != null){
			count = 1;
			Tree child = node.child;
			Tree brother = child.brother;
			while(brother != null){
				count++;
				brother = brother.brother;
			}
		}
		return count;
	}

	/**
	 * 生成给定树的HTML表示
	 * @param tree
	 * @return 
	 */



	private static String generateItemDiv(Tree tree) {
		StringBuffer sb = new StringBuffer(1024);
		boolean isLastNode = tree.isLast();

		boolean isFolder = false;
		if(tree.child != null){
			isFolder = true;
			tree.icon =  "/foldericon.gif";
			tree.openIcon = "/openfolder_2.gif";

		}else{//leaf can not open
			tree.open = false;
			tree.icon = "/file.gif";
		}

		sb.append("<div id=\"webfx-tree-object-").append(tree.variableId).append("\" ").append("isFolder='").append(isFolder).append("'").append(" isLastNode='").append(isLastNode).append("' ").append(" ondblclick=\"toggle(this);\" class=\"webfx-tree-item\" >");
		//creat indent
		int indentCount = 0;
		Tree parentNode = tree.parent;
		List<String> indentList = new LinkedList<String>();
		
		while(parentNode !=null && !parentNode.isRoot()){
			StringBuffer indentBuffer = new StringBuffer();
			indentList.add(indentBuffer.append("<img id=\"webfx-tree-object-").append(tree.variableId).append("-indent-").append(indentCount++).append("\" src=\"").append(tree.getImagePath()).append(parentNode.isLast() ? "/blank.gif\">" : "/I.gif\">").toString());
			parentNode = parentNode.parent;
		}
		for(int i = indentList.size() ;i > 0 ;){
			sb.append(indentList.get(--i));
		}
		sb.append("<img id=\"webfx-tree-object-" ).append(tree.variableId).append("-plus\" onclick=\"toggle(this.parentNode);\" src=\"" ).append(tree.getImagePath()).append(isFolder ? (tree.open ? (isLastNode ? ("/Lminus.gif"):("/Tminus.gif")):(tree.parent.isLast() ? "/Lplus.gif":"/Tplus.gif")):(tree.isLast()  ? "/L.gif":"/T.gif" )).append("\">");
		sb.append("<img id=\"webfx-tree-object-").append(tree.variableId).append("-icon\" class=\"webfx-tree-icon\" src=\"").append(tree.getImagePath()).append(tree.open ? tree.openIcon : tree.icon).append("\" >");
		sb.append("<a href='javascript:void(0);' value='" ).append( tree.value ).append( "'  text='" ).append( tree.label).append( "' onclick=\"" ).append( tree.onClick ).append( "\" id=\"").append(tree.variableId).append( "-anchor\" ");
		sb.append(" style='text-decoration: none;'>");
		sb.append(tree.label).append("</a></div>");
		sb.append("<div id=\"webfx-tree-object-" ).append(tree.variableId).append("-cont\" class=\"webfx-tree-container\" style=\"display: " ).append(((tree.open)?"block":"none") ).append( ";\">");
		//get child count
		int childCount = tree.getChildrenCount();
		Tree child = tree.child;
		for(int index = 0 ;index < childCount ; index++){
			
			sb.append(generateItemDiv(child));
			child = child.brother;
		}

		sb.append("</div>");

		return sb.toString();
	}


	//目前暂不处理带有Input类型的树
	private static String generateHTMLTree(Tree tree) {
		if(!tree.isRoot()){
			throw new IllegalArgumentException("the tree must be root");
		}
		StringBuffer root = new StringBuffer(1024);
		//create tree div
		root.append("<div id='webfx-tree-object-").append(tree.variableId).append("'  ondblclick=\"toggle(this);\" class=\"webfx-tree-item\" >");
		//append image
		root.append("<img id=\"webfx-tree-object-").append(tree.variableId).append("-icon\" class=\"webfx-tree-icon\"  src=\"").append(tree.getImagePath()).append("/").append(tree.open ? tree.getOpenIcon() : tree.getIcon()).append("\" >");
		//create link
		root.append("<a href='#' value='").append(tree.value).append("' text='" ).append(tree.label).append("' onclick=\"").append(tree.onClick).append("\" id=\"webfx-tree-object-" ).append( tree.variableId  ).append( "-anchor\" ");
		root.append(" style='text-decoration: none;'>" ).append(tree.label).append("</a></div>");
		//create child div
		root.append("<div id=\"webfx-tree-object-" ).append(tree.variableId).append( "-cont\" class=\"webfx-tree-container\" style=\"display: ").append(tree.open ? "block":"none").append(";\">");
		//child nodes content
		//get child count
		int childCount = tree.getChildrenCount();
		Tree child = tree.child;
		for(int index = 0 ;index < childCount ; index++){
			root.append(generateItemDiv(child));
			child = child.brother;
		}
		//tree end
		root.append("</div>");

		return root.toString();
	}
	/**
	 * 生成树的根
	 *
	 * @param tree 树根节点
	 * @return root 生成树根的js
	 * WebFXTree(sText, sAction, bshowInput, bChecked ,onCheck, sValue ,sBehavior, sIcon, sOpenIcon)
	 */
	private static String generateRoot(Tree tree) {
		StringBuffer root = new StringBuffer(512);
		root.append("var root = new WebFXTree(\"").append(tree.label).append("\"");
		if(tree.onClick != null){//当checkbox被选中时的触发动作
			root.append(",\" ").append(tree.onClick).append("\"");
		}else{
			root.append(", null");
		}
		root.append(", ").append(tree.showInput);
		root.append(", ").append(tree.isChecked);

		if(tree.onCheck != null){//当checkbox被选中时的触发动作
			root.append(",\" ").append(tree.onCheck).append("\"");
		}else{
			root.append(", null");
		}
		root.append(", \"").append(tree.value).append("\"");

		if (ONLY_FOLDER) {
			root.append(", \"explorer\"");
		} else {
			root.append(", \"classic\"");
		}
		//添加图标
		if(tree.icon != null){//当checkbox被选中时的触发动作
			root.append(",\" ").append(tree.icon).append("\"");
		}else{
			root.append(", null");
		}
		if(tree.openIcon != null){//当checkbox被选中时的触发动作
			root.append(",\" ").append(tree.openIcon).append("\"");
		}else{
			root.append(", null");
		}
		root.append(");");

		return root.toString();
	}

	/**
	 * 生成一个树节点
	 *
	 * @param tree 树节点对象
	 * @return treeItem 树节点的js代码
	 * WebFXTreeItem(sText, sAction, bshowInput,inputType, onCheck, bChecked ,sValue ,tip,eParent, sIcon, sOpenIcon)
	 */
	private static String generateItem(Tree tree) {
		StringBuilder item = new StringBuilder("\n");
		item.append("var ").append(prefix).append(tree.variableId).append("= new WebFXTreeItem(\"").append(tree.label).append("\"");
		if(tree.onClick != null){//当checkbox被选中时的触发动作
			item.append(",\" ").append(tree.onClick).append("\"");
		}else{
			item.append(", null");
		}
		if(tree.showInput){//是否显示Checkbox
			item.append(", ").append(tree.showInput);
			item.append(", \"").append(tree.inputType).append("\"");
			if(tree.onCheck != null){//当checkbox被选中时的触发动作
				item.append(",\" ").append(tree.onCheck).append("\"");
			}else{
				item.append(", null");
			}
			item.append(",").append(tree.isChecked);
			if(tree.value != null){
				item.append(",\"").append(tree.value).append("\"");
			}
		}else if(!"".equals(tree.value)){
			item.append(", false, null, null, false").append(",\"").append(tree.value).append("\"");
		}
		if(tree.tip != null){
			item.append(",\"").append(tree.tip).append("\""); 
		}

		item.append(",null"); //设置eParent
		//设置图标
		if(tree.icon != null){//当checkbox被选中时的触发动作
			item.append(",\" ").append(tree.icon).append("\"");
		}else{
			item.append(", null");
		}
		if(tree.openIcon != null){//当checkbox被选中时的触发动作
			item.append(",\" ").append(tree.openIcon).append("\"");
		}else{
			item.append(", null");
		}

		item.append(");");
		item.append("\n").append(tree.parent.variable()).append(".add(").append(tree.variable()).append(");");
		return item.toString();
	}

	/**
	 * 为当前节点添加子节点
	 *
	 * @param child 待添加的子节点
	 * @return child 被添加的子节点
	 */
	public Tree addChild(Tree child) {
		Tree node = this.parent;
		while(node != null){
			if(node.equals(child)){
				throw new RuntimeException("不能添加父节点作为子节点...");
			}
			node = node.parent;
		}
		if (this.child != null) {
			//has child ,add the given child as the younger brother of the elder child
			Tree elder = this.child;
			return elder.addBrother(child);
		} else {
			//has no child,add this as the first child
			this.child = child;
			child.parent = this;
		}

		return child;
	}

	/**
	 * 添加子节点
	 *
	 * @param label  子节点上显示的名称
	 * @param script 点击子节点时触发的动作
	 * @return Tree 被添加的子树节点
	 */
	public Tree addChild(String label, String script) {
		Tree son = new Tree(label, script);
		return addChild(son);
	}
	/**
	 * 添加子节点
	 *
	 * @param label  子节点上显示的名称
	 * @param script 点击子节点时触发的动作
	 * @param value 子节点的值
	 * @return Tree 被添加的子树节点
	 */
	public Tree addChild(String label, String script,String value) {
		Tree son = new Tree(label, script);
		son.setValue(value);
		return addChild(son);
	}
	/**
	 * 添加子节点
	 *
	 * @param label 子节点上显示的名称
	 * @return child 被添加的子树节点
	 */
	public Tree addChild(String label) {
		return addChild(label, null);
	}

	/**
	 * 添加当前树节点的兄弟节点
	 *
	 * @param younger 待添加的兄弟节点
	 * @return Tree 被添加的兄弟节点
	 */
	public Tree addBrother(Tree younger) {
		Tree node = this.parent;
		while(node != null){
			if(node.equals(younger)){
				throw new RuntimeException("不能添加父节点作为兄弟节点...");
			}
			node = node.parent;
		}
		if (isRoot()) {
			// if this is the root ,add the given node as brother
			return addChild(younger);
		}
		Tree elder = this;
		//get the youngest brother
		while (elder.brother != null) {
			elder = elder.brother;
		}
		//add the younger as the yongest brother
		elder.brother = younger;
		younger.parent = elder.parent;
		return younger;

	}

	/**
	 * 为当前节点添加兄弟节点
	 *
	 * @param label  兄弟节点上显示的文字
	 * @param script 点击兄弟节点时触发的动作
	 * @return Tree 被添加的兄弟节点
	 */
	public Tree addBrother(String label, String script) {
		Tree younger = new Tree(label, script);
		return addBrother(younger);
	}

	/**
	 * 为当前节点添加兄弟节点
	 *
	 * @param label 兄弟节点上显示的文字
	 * @return Tree 被添加的兄弟节点
	 */
	public Tree addBrother(String label) {
		return addBrother(label, null);
	}

	/**
	 * 返回当前节点的最终根节点
	 *
	 * @return root 当前节点的最终根节点
	 */
	public Tree getRoot() {
		Tree tree = this;
		while (tree.parent != null) {
			tree = tree.parent;
			if(tree == this){
				throw new RuntimeException("树父子节点出现闭环引用...");
			}
		}
		return tree;
	}

	/**
	 * 设置点击树形控件时触发的动作
	 *
	 * @param script 待设置的动作
	 */
	public void setOnClick(String script) {
		if(script != null){
			this.onClick = script.startsWith("javascript:") ? script: "javascript:" + script;
		}
	}

	/**
	 * 设置树形控件上显示的文字
	 *
	 * @param label 待显示的文字
	 */
	public void setLabel(String label) {
		this.label = label;
	}

	public String toString() {
		return getTree();
	}




	public Tree getParent() {
		return parent;
	}
	public void setParent(Tree parent) {		
		if (null != parent) {
			parent.addChild(this);
		}
	}
	public boolean isShowInput() {
		return showInput;
	}
	public void setShowInput(boolean showInput) {
		this.showInput = showInput;
	}
	public int getVariableId() {
		return variableId;
	}
	public void setVariableId(int variableId) {
		this.variableId = variableId;
	}
	public boolean isChecked() {
		return isChecked;
	}
	public String getLabel() {
		return label;
	}

	public int getLevel(){
		int level = 0;
		if(this.parent != null){
			Tree tree = this;
			while (tree.parent != null) {
				level ++;
				tree = tree.parent;
			}
		}
		return level;
	}
	public String getOnCheck() {
		return onCheck;
	}
	public String getOnClick() {
		return onClick;
	}
	public String getValue() {
		return value;
	}


	private static Tree createTreeFormXML(Element element,Tree node){
		List children = element.elements();
		if(node == null){
			node = new Tree("root");
		}
		for(Object c : children){
			Element childElement = (Element)c;
			Tree child = node.addChild(childElement.attributeValue("text"),childElement.attributeValue("onclick"));
			child.setValue(childElement.attributeValue("id"));
			createTreeFormXML(childElement,child);
		}
		return node;
	}


	public static String xmlTreeToHTML(String xml,Tree rootTree){
		Document document = (Document)XMLUtil.StringToNode(xml);
		Element rootElement = document.getRootElement();
		return createTreeFormXML(rootElement, rootTree).getHTML();
	}
	

	/**
	 * create xml tree
	 * @return
	 */
	public static XMLTree createXMLTree(){
		return new XMLTree();
	}
	/**
	 * 2007-9-30 下午02:48:36
	 * Author:yangdongyu(yangdy@bingosoft.net)
	 * ReadMe:生成xmltree的帮助类
	 * ChangeLog:
	 */
	public static class XMLTree{
		public static final String xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><tree ";
		public static final String xmlFooter = "</tree>";
		private String text;
		private String src;
		private String value;
		private String onclick;
		private boolean showInput;
		private String oncheck;
		private boolean checked = false;
		private String icon;
		private String openIcon;
		private String target;
		private String inputType;
		private XMLTree parent;


		private List<XMLTree> children = new ArrayList<XMLTree>(0);
		/**
		 * 添加子节点
		 * @param child
		 */
		public void addChild(XMLTree child){
			child.parent = this;
			this.children.add(child);
		}
		/**
		 * @param checked the checked to set
		 */
		public XMLTree setChecked(boolean checked) {
			this.checked = checked;
			return this;
		}
		/**
		 * @param icon the icon to set
		 */
		public XMLTree setIcon(String icon) {
			this.icon = icon;
			return this;
		}
		/**
		 * @param openIcon the openIcon to set
		 */
		public XMLTree setOpenIcon(String openIcon) {
			this.openIcon = openIcon;
			return this;
		}
		/**
		 * @param target the target to set
		 */
		public XMLTree setTarget(String target) {
			this.target = target;
			return this;
		}
		/**
		 * @param onCheck the onCheck to set
		 */
		public XMLTree setOncheck(String onCheck) {
			this.oncheck = onCheck;
			return this;
		}
		/**
		 * @param onclick the onclick to set
		 */
		public XMLTree setOnclick(String onclick) {
			if(onclick != null){
				this.onclick =onclick.startsWith("javascript:") ? onclick : ("javascript:" + onclick);
			}
			return this;
		}
		/**
		 * @param showInput the showInput to set
		 */
		public XMLTree setshowInput(boolean showInput) {
			this.showInput = showInput;
			return this;
		}
		/**
		 * @param src the src to set
		 */
		public XMLTree setSrc(String src) {
			this.src = BeanHelper.filter(src);
			return this;
		}
		public String getText() {
			return text;
		}
		public String getValue() {
			return value;
		}
		/**
		 * @param text the text to set
		 */
		public XMLTree setText(String text) {
			this.text = text;
			return this;
		}
		/**
		 * @param value the value to set
		 */
		public XMLTree setValue(String value) {
			this.value = value;
			return this;
		}
		/**
		 * showRadio
		 */
		public void showRadio() {
			this.showInput = true;
			this.inputType = "radio";
		}
		/**
		 * showCheckbox
		 *
		 */
		public void showCheckbox() {
			this.showInput = true;
			this.inputType = "checkbox";
		}
		/**
		 * 获取当前树节点在整棵树中的绝对路径
		 * @return
		 */
		public String getAbsolutePath(){
			String path = this.text;
			XMLTree temp = this;
			while(temp.parent != null && temp.parent.text != null){
				path = temp.parent.text + "/" + path;
				temp = temp.parent;
			}
			return path;
		}
		/**
		 * 通过绝对路径选中对应的根节点
		 * @param absolutePaths
		 */
		public void setCheckedByAbsolutePath(List<String> absolutePaths){
			for(String path : absolutePaths){
				if(this.getAbsolutePath().equals(path)){
					this.setChecked(true);
				}
				if(!this.children.isEmpty()){
					for(XMLTree child : this.children){
						child.setCheckedByAbsolutePath(absolutePaths);
					}
				}
			}
		}
		/**
		 * 创建一个子节点
		 * @return
		 */
		public XMLTree createChild(){
			XMLTree child = new XMLTree();
			this.addChild(child);
			return child;
		}

		private void toXML(StringBuilder sb){
			sb.append("<tree ");
			if(this.text != null){
				sb.append("text=\"").append(this.text).append("\" ");
			}
			if(this.src != null){
				sb.append("src=\"").append(this.src).append("\" ");
			}
			if(this.value != null){
				sb.append("value=\"").append(this.value).append("\" ");
			}
			if (this.onclick != null) {
				sb.append("onclick=\"").append(this.onclick).append("\" ");
			}			
			if (this.showInput) {
				sb.append("showInput=\"").append(this.showInput).append("\" ");
			}
			if (this.inputType != null) {
				sb.append("inputType=\"").append(this.inputType).append("\" ");
				if(this.inputType.equals("checkbox")){
					sb.append("showCheckbox=\"").append(true).append("\" ");
				}else if(this.inputType.equals("radio")){
					sb.append("showRadio=\"").append(true).append("\" ");
				}
			}
			if (this.oncheck != null) {
				sb.append("oncheck=\"").append(this.oncheck).append("\" ");
			}
			if (this.checked) {
				sb.append("checked=\"").append(this.checked).append("\" ");
			}		
			if (this.icon != null) {
				sb.append("icon=\"").append(this.icon).append("\" ");
			}
			if (this.openIcon != null) {
				sb.append("openIcon=\"").append(this.openIcon).append("\" ");
			}	
			if (this.target != null) {
				sb.append("target=\"").append(this.target).append("\"");
			}
			sb.append(" >");
			if(this.children != null && !this.children.isEmpty()){
				for(XMLTree child : children){
					child.toXML(sb);
				}
			}
			sb.append("</tree>");
		}
		public String getTree(){
			StringBuilder sb = new StringBuilder();
			sb.append(xmlHeader);
			if(this.text != null){
				sb.append("text=\"").append(this.text).append("\" ");
			}
			if(this.src != null){
				sb.append("src=\"").append(this.src).append("\" ");
			}
			if(this.value != null){
				sb.append("value=\"").append(this.value).append("\" ");
			}
			if (this.onclick != null) {
				sb.append("onclick=\"").append(this.onclick).append("\" ");
			}			
			if (this.showInput) {
				sb.append("showInput=\"").append(this.showInput).append("\" ");
			}			
			if (this.oncheck != null) {
				sb.append("oncheck=\"").append(this.oncheck).append("\" ");
			}
			if (this.checked) {
				sb.append("checked=\"").append(this.checked).append("\" ");
			}		
			if (this.icon != null) {
				sb.append("icon=\"").append(this.icon).append("\" ");
			}
			if (this.openIcon != null) {
				sb.append("openIcon=\"").append(this.openIcon).append("\" ");
			}	
			if (this.target != null) {
				sb.append("target=\"").append(this.target).append("\" ");
			}
			sb.append(">");
			for(XMLTree child : children){
				child.toXML(sb);
			}
			sb.append(xmlFooter);
			return sb.toString();
		}
		public String toString(){
			return getTree();
		}
	}
	public String getNodeId() {
		return nodeId;
	}

	public void setNodeId(String nodeId) {
		this.nodeId = nodeId;
	}
	public String getIcon() {
		if(this.icon == null){
			if(this.parent != null){
				return this.parent.getIcon(); 
			}
		}
		return icon;
	}
	public void setIcon(String icon) {
		this.icon = icon;
	}


	public String getOpenIcon() {
		if(this.openIcon == null){
			if(this.parent != null){
				return this.parent.getOpenIcon(); 
			}
		}
		return openIcon;
	}
	public void setOpenIcon(String openIcon) {
		this.openIcon = openIcon;
	}
	public String getImagePath() {
		if(this.imagePath == null){
			if(this.parent != null){
				return this.parent.getImagePath(); 
			}
		}
		return imagePath;
	}
	public void setImagePath(String imagePath) {
		this.imagePath = imagePath;
	}

}
